﻿// --------------------------------------------------------------------------------------------------------------------- 
// <copyright file="Problem25.cs" company="Microsoft">
//   Copyright (c) Microsoft Corporation.  All rights reserved. THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// </copyright>
// <summary>
//   Defines the Problem25 type.
// </summary>
// ---------------------------------------------------------------------------------------------------------------------
namespace EulerProblemsCSharp.Problems
{
    using System.Linq;

    using Microsoft.FSharp.Math;

    /// <summary>
    /// Problem 25.
    /// </summary>
    public class Problem25 : ProblemBase
    {
        /// <summary>
        /// Gets Number.
        /// </summary>
        /// <value>
        /// The number.
        /// </value>
        public override int Number
        {
            get
            {
                return 25;
            }
        }

        /// <summary>
        /// Gets Description.
        /// </summary>
        /// <value>
        /// The description.
        /// </value>
        public override string Description
        {
            get
            {
                return "What is the first term in the Fibonacci sequence to contain 1000 digits?";
            }
        }

        /// <summary>
        /// Solves the problem.
        /// </summary>
        /// <returns>
        /// The solution.
        /// </returns>
        public override object Solve()
        {
            ////var answer = this.SolveUsingStrings();
            var answer = this.SolveUsingBigInts();

            return answer;
        }

        /// <summary>
        /// Solves the problem using strings. Stupid implementation.
        /// </summary>
        /// <returns>
        /// The solution.
        /// </returns>
        private object SolveUsingStrings()
        {
            var i = 0;

            var query = from number in new Fibonacci().BigSequence
                        select new { number, length = number.ToString().Length, position = ++i }
                        into numberdetail
                                where numberdetail.length == 1000
                                select numberdetail.position;

            var answer = query.First();

            return answer;
        }

        /// <summary>
        /// Solves the problem using big ints.
        /// </summary>
        /// <returns>
        /// The solution.
        /// </returns>
        private object SolveUsingBigInts()
        {            
            var ten = new BigInt(10);
            var nineninenine = new BigInt(999);
            var first1000DigitNumber = BigInt.Pow(ten, nineninenine);

            var answer = new Fibonacci().BigSequence
                                .TakeWhile(x => x < first1000DigitNumber)
                                .Count() + 1;

            return answer;             
        }
    }
}